import javax.media.opengl.*;
import jocode.*;
import processing.opengl.*;

// handles for textures
int marbleTextureHandle = 0;
int groundTextureHandle = 0;
// light position: 
//  if last value is 0, then this describes light direction
//  if 1, then light position
float lightPosition1[] = { 0f, 0f, 0f, 1f };
float lightPosition2[] = { 0f, -10f, 0f, 0f };
float lightPosition3[] = { 0f, 0f, 0f, 1f };
// rotation of sphere
float rotation = 0;
// display lists
int sphereDL = 0, cubeDL = 0;

void setup() {
  size(800, 600, OPENGL);
  JOBridgeP5.init(this);

  // Create sphere texture
  marbleTextureHandle = JOApp.makeTexture("marble.jpg");

  // Create texture for ground plane
  groundTextureHandle = JOApp.makeTexture("mahog_texture.jpg");

  sphereDL = JOApp.beginDisplayList(); 
  {
    JOApp.renderSphere();
  }
  JOApp.endDisplayList();

  cubeDL = JOApp.beginDisplayList(); 
  {
    JOApp.renderCube(10,40);
  }
  JOApp.endDisplayList();
}

// set the camera position, field of view, depth
void setPerspective() {
  // select projection matrix (controls perspective)
  JOApp.gl.glMatrixMode(GL.GL_PROJECTION);
  JOApp.gl.glLoadIdentity();
  // fovy, aspect ratio, zNear, zFar
  JOApp.glu.gluPerspective(30f, JOApp.aspectRatio, 1f, 100f);
  // return to modelview matrix
  JOApp.gl.glMatrixMode(GL.GL_MODELVIEW);
}

void setLights() {
  // create a point light (white)
  JOApp.setLight(GL.GL_LIGHT1,
                 new float[] { 1.0f, 1.0f, 1.0f, 1.0f },  // diffuse color
                 new float[] { 0.2f, 0.2f, 0.2f, 1.0f },  // ambient
                 new float[] { 1.0f, 1.0f, 1.0f, 1.0f },  // specular
                 lightPosition1);                         // position

  // create a directional light (dark red, to simulate reflection off wood surface)
  JOApp.setLight(GL.GL_LIGHT2,
                 new float[] { 0.95f, 0.35f, 0.15f, 1.0f },  // diffuse color
                 new float[] { 0.0f,  0.0f,  0.0f,  1.0f },  // ambient
                 new float[] { 0.03f, 0.0f,  0.0f,  1.0f },  // specular
                 lightPosition2);                            // position (pointing up)

  // create a point light (dark blue, to simulate reflection off wood surface)
  JOApp.setLight(GL.GL_LIGHT3,
                 new float[] { 0.35f, 0.45f, 0.95f, 1.0f },  // diffuse color
                 new float[] { 0.0f,  0.0f,  0.0f,  1.0f },  // ambient
                 new float[] { 0.3f,  0.4f,  0.7f,  1.0f },  // specular
                 lightPosition3 );                           // position (pointing up)

  // no overall scene lighting
  JOApp.setAmbientLight(new float[] { 0.0f, 0.0f, 0.0f, 0.0f });
}

void draw() {
  // rotate 25 degrees per second
  rotation += 25f * (1f / frameRate);

  JOApp.begin();
  {
    // clear depth buffer and color buffers
    JOApp.gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

    // setup and enable perspective
    setPerspective();

    // set the lights
    setLights();

    // enable lighting and texture rendering
    JOApp.gl.glEnable(GL.GL_LIGHTING);
    JOApp.gl.glEnable(GL.GL_TEXTURE_2D);

    // select model view for subsequent transforms
    JOApp.gl.glMatrixMode(GL.GL_MODELVIEW);
    JOApp.gl.glLoadIdentity();

    // set the viewpoint
    JOApp.glu.gluLookAt(0f,  3f, 15f,   // where is the eye
                        0f, -1f,  0f,   // what point are we looking at
                        0f,  1f,  0f);  // which way is up

    //---------------------------------------------------------------
    // desktop
    //---------------------------------------------------------------

    // dark reddish material
    JOApp.setMaterial(new float[] { 0.8f, 0.3f, 0.2f, 1.0f }, .2f); 

    // enable texture
    JOApp.gl.glBindTexture(GL.GL_TEXTURE_2D, groundTextureHandle);

    // draw the ground plane
    JOApp.gl.glPushMatrix();
    {
      JOApp.gl.glTranslatef(0f, -7f, 0f);  // down a bit
      JOApp.callDisplayList(cubeDL);
    }
    JOApp.gl.glPopMatrix();


    // orbit
    JOApp.gl.glRotatef(rotation, 0,1,0);
    JOApp.gl.glTranslatef(3,0,0);

    JOApp.gl.glRotatef(rotation/2, 0,1,0);
    JOApp.gl.glTranslatef(-2,0,0);

    //---------------------------------------------------------------
    // glowing white ball
    //---------------------------------------------------------------

    // for point lights set position each frame so light moves with scene
    // white light at same position as marble ball
    JOApp.setLightPosition(GL.GL_LIGHT1, lightPosition1);

    // glowing white material
    JOApp.setMaterial(new float[] { 1.0f, 1.0f, 1.0f, 1.0f },  // diffuse color
                      new float[] { 1.0f, 1.0f, 1.0f, 1.0f },  // ambient
                      new float[] { 0.0f, 0.0f, 0.0f, 1.0f },  // specular
                      new float[] { 1.0f, 1.0f, 1.0f, 1.0f },  // emissive
                      0f);                                     // not shiny

    // enable texture
    JOApp.gl.glBindTexture(GL.GL_TEXTURE_2D, marbleTextureHandle);

    // draw marble sphere
    JOApp.gl.glPushMatrix();
    {
      JOApp.gl.glScalef(.5f, .5f, .5f);    // make it smaller
      JOApp.callDisplayList(sphereDL);       // draw the sphere display list
    }
    JOApp.gl.glPopMatrix();

    // orbit
    JOApp.gl.glRotatef(rotation*1.4f, 0,1,0);
    JOApp.gl.glTranslatef(4,0,0);

    //---------------------------------------------------------------
    // shiny blue ball
    //---------------------------------------------------------------

    // shiny dark blue material
    JOApp.setMaterial(new float[] { 0.3f, 0.3f, 0.6f, 1.0f }, .9f); 

    // set blue light at same spot as blue sphere
    JOApp.setLightPosition(GL.GL_LIGHT3, lightPosition3);

    // no texture (texture handle 0)
    JOApp.gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

    // Draw sphere
    JOApp.gl.glPushMatrix();
    {
      JOApp.gl.glScalef(1.6f, 1.6f, 1.6f);  // make it smaller
      JOApp.callDisplayList(sphereDL);
    }
    JOApp.gl.glPopMatrix();
  }
  JOApp.end();
}

